package com.surge;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class SurgeTest {
	
	private SessionFactory sessionFactory;
	// 生产环境不允许 把session与transaction 设置成成员变量，因为涉及到并发问题
	private Session session;
	private Transaction transaction;
	
	// junit 方法init 与 destory。 这样只需要test中写主要的业务测试逻辑
	@Before
	public void init(){
		//1、 版本5.x	
		final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
				.configure() // configures settings from hibernate.cfg.xml
				.build();
		try {
			sessionFactory = new MetadataSources( registry ).buildMetadata().buildSessionFactory();
		}
		catch (Exception e) {
			System.out.println(e);
			StandardServiceRegistryBuilder.destroy( registry );
		}
		// 2. 创建一个 Session 对象
		session = sessionFactory.openSession();

		// 3. 开启事务
		transaction = session.beginTransaction();
	}
	@After
	public void destory(){
		// 5. 提交事务
		transaction.commit();

		// 6. 关闭 Session
		session.close();

		// 7. 关闭 SessionFactory 对象
		sessionFactory.close();
	}
	
	/*
	 * ============================    测试逻辑代码    ============================
	 */
	
	/*
	 * 给予外键约束
	 */
	
	
	@Test
	public void testSave(){
		
		Department department = new Department();
		department.setDeptName("DEPT-BB");
		
		Manager manager = new Manager();
		manager.setMgrName("MGR-BB");
		
		//设定关联关系
		department.setMgr(manager);
		manager.setDept(department);
		
		//保存操作 ： 两条insert 一条update
		//建议先保存没有外键列的那个对象. 这样会减少 UPDATE 语句
//		session.save(department); // 部门配置文件中 配置了外键唯一性约束
//		session.save(manager);
		
		session.save(manager); // 两条insert 没有update
		session.save(department);
		
		
	}
	
	/**
	 *  
	 */
	@Test
	public void testGet(){
		//1. 默认情况下对关联属性使用懒加载
		Department dept = (Department) session.get(Department.class, 1);
		System.out.println(dept.getDeptName()); 
		
		//2. 所以会出现懒加载异常的问题. 
//		session.close();  // 不能关闭，报错
//		Manager mgr = dept.getMgr();
//		System.out.println(mgr.getClass()); 
//		System.out.println(mgr.getMgrName()); 
		
		//3. 查询 Manager 对象的连接条件应该是 dept.manager_id = mgr.manager_id
		//  而不应该是 dept.dept_id = mgr.manager_id， 因为没有在 one-2-one中配置 property-ref="mgr"
		Manager mgr = dept.getMgr(); 
		/*
		 *  两次查询。先级联查询 获取关联manager信息，再查询manager表
		 *  from
        		MANAGERS manager0_ 
    		left outer join
        		DEPARTMENTS department1_ 
            on manager0_.MGR_ID=department1_.MGR_ID
		 */
		System.out.println(mgr.getMgrName()); 
		
		
	}
	
	@Test
	public void testGet2(){
		/*
		 * 在查询没有外键的实体对象时, 使用的左外连接查询, 一并查询出其关联的对象
		 * 并已经进行初始化. 
		 */
		Manager mgr = (Manager) session.get(Manager.class, 1); // 只执行一条级联查询
		// 因为manger表没有外键，那么hibernate要进行后续操作没办法注入Dept信息，只能级联查询。
		System.out.println(mgr.getMgrName()); 
		System.out.println(mgr.getDept().getDeptName()); 
	}
	
}
